﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Collections;

namespace TestBalance
{
    public partial class FormMain : Form
    {
        /// <summary>
        /// 神经元细胞膜电容
        /// </summary>
        public const float Capacitance = 0.01f;

        Thread ThreadReceptor;
        Thread ThreadNeuron;
        Thread ThreadEffector;

        //输入数据
        byte DataInput = 0;
        //输出数据
        byte DataOutput = 0;

        Random random = new Random((int)DateTime.Now.Ticks);

        //离子
        Dictionary<IonType, Ion> Ions = new Dictionary<IonType, Ion>();

        //第一信使
        Queue<FirstMessenger> FirstMessengersCombined = new Queue<FirstMessenger>();
        Queue<FirstMessenger> FirstMessengersDetached = new Queue<FirstMessenger>();

        //受体
        Queue<Receptor> ReceptorsActivated = new Queue<Receptor>();
        Queue<Receptor> ReceptorsInactivated = new Queue<Receptor>();

        //G蛋白
        Queue<GProtein> GProteinsActivated = new Queue<GProtein>();
        Queue<GProtein> GProteinsInactivated = new Queue<GProtein>();

        //第二信使酶
        Queue<SecondMessengerEnzyme> SecondMessengersEnzymeCombined = new Queue<SecondMessengerEnzyme>();
        Queue<SecondMessengerEnzyme> SecondMessengersEnzymeDetached = new Queue<SecondMessengerEnzyme>();

        //第二信使
        Queue<SecondMessenger> SecondMessengersActivated = new Queue<SecondMessenger>();
        Queue<SecondMessenger> SecondMessengersInactivated = new Queue<SecondMessenger>();

        //蛋白激酶
        Queue<ProteinKinase> ProteinKinasesActivated = new Queue<ProteinKinase>();
        Queue<ProteinKinase> ProteinKinasesInactivated = new Queue<ProteinKinase>();

        //离子通道
        Queue<IonChannel> IonChannelCombined = new Queue<IonChannel>();
        Queue<IonChannel> IonChannelDetached = new Queue<IonChannel>();

        //蛋白磷酸酶
        List<ProteinPhosphatase> ProteinPhosphatases = new List<ProteinPhosphatase>();

        public FormMain()
        {
            InitializeComponent();

            //初始化离子
            Ions.Add(IonType.K, new Ion(IonType.K, 0));
            Ions.Add(IonType.Na, new Ion(IonType.Na, 0));

            //初始化第一信使
            for (int i = 0; i < 255; i++)
            {
                FirstMessengersDetached.Enqueue(new FirstMessenger());
            }

            //初始化受体
            for (int i = 0; i < 255; i++)
            {
                ReceptorsInactivated.Enqueue(new Receptor());
            }

            //初始化G蛋白
            for (int i = 0; i < 2550; i++)
            {
                GProteinsInactivated.Enqueue(new GProtein());
            }

            //初始化第二信使酶
            for (int i = 0; i < 2550; i++)
            {
                SecondMessengersEnzymeDetached.Enqueue(new SecondMessengerEnzyme());
            }

            //初始化第二信使
            for (int i = 0; i < 2550; i++)
            {
                SecondMessengersInactivated.Enqueue(new SecondMessenger(1));
            }

            //初始化蛋白激酶
            for (int i = 0; i < 2550; i++)
            {
                ProteinKinasesInactivated.Enqueue(new ProteinKinase());
            }

            //初始化离子通道
            for (int i = 0; i < 2550; i++)
            {
                IonChannelDetached.Enqueue(new IonChannel(Ions[IonType.Na], 1));
            }

            //初始化蛋白磷酸酶
            for (int i = 0; i < 10; i++)
            {
                ProteinPhosphatases.Add(new ProteinPhosphatase());
            }


            ThreadReceptor = new Thread(new ThreadStart(ReceptorOperator));
            ThreadNeuron = new Thread(new ThreadStart(NeuronOperator));
            ThreadEffector = new Thread(new ThreadStart(EffectorOperator));

            ThreadReceptor.Start();
            ThreadNeuron.Start();
            ThreadEffector.Start();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            ThreadReceptor.Abort();
            ThreadNeuron.Abort();
            ThreadEffector.Abort();
        }

        public void ReceptorOperator()
        {
            while (true)
            {
                DataInput = (byte)random.Next(256);

                //将接收的数据转换成第一信使的数量
                for (int i = 0; i < DataInput; i++)
                {
                    if (FirstMessengersDetached.Count == 0) break;

                    FirstMessengersCombined.Enqueue(FirstMessengersDetached.Dequeue());
                }

                //暂停10秒
                Thread.Sleep(new TimeSpan(100000000));
            }
        }

        public void NeuronOperator()
        {
            while (true)
            {
                while( FirstMessengersCombined.Count > 0 && ReceptorsInactivated.Count > 0)
                {
                    FirstMessenger FM = FirstMessengersCombined.Dequeue();
                    Receptor R = ReceptorsInactivated.Dequeue();

                    //第一信使与受体结合,改变受体的蛋白质构象
                    R.Combine(FM);

                    //受体被激活
                    ReceptorsActivated.Enqueue(R);
                }

                while (ReceptorsActivated.Count > 0)
                {
                    Receptor R = ReceptorsActivated.Dequeue();

                    //激活的受体激活一定数量的G蛋白
                    R.Activate(GProteinsActivated, GProteinsInactivated);

                    //受体与第一信使分离,受体构象还原
                    R.Detach(FirstMessengersDetached);

                    //受体失活
                    ReceptorsInactivated.Enqueue(R);
                }

                
                while (GProteinsActivated.Count > 0 && SecondMessengersEnzymeDetached.Count > 0)
                {
                    GProtein GP = GProteinsActivated.Dequeue();
                    
                    SecondMessengerEnzyme SME = SecondMessengersEnzymeDetached.Dequeue();

                    //激活的G蛋白与第二信使酶结合
                    SME.Combine(GP);

                    //第二信使酶激活
                    SecondMessengersEnzymeCombined.Enqueue(SME);
                }

                
                while (SecondMessengersEnzymeCombined.Count > 0)
                {
                    SecondMessengerEnzyme SME = SecondMessengersEnzymeCombined.Dequeue();

                    //激活的第二信使酶激活或抑制第二信使
                    SME.Operate(SecondMessengersActivated, SecondMessengersInactivated);

                    //第二信使酶与G蛋白分离
                    SME.Detach(GProteinsInactivated);

                    //第二信使酶失活
                    SecondMessengersEnzymeDetached.Enqueue(SME);

                }

                while (SecondMessengersActivated.Count > 0)
                {
                    SecondMessenger SM = SecondMessengersActivated.Dequeue();

                    //激活一定数量的蛋白激酶
                    SM.Activate(ProteinKinasesActivated, ProteinKinasesInactivated);

                    //第二信使失活
                    SecondMessengersInactivated.Enqueue(SM);
                }

                while (ProteinKinasesActivated.Count > 0 && IonChannelDetached.Count > 0)
                {
                    ProteinKinase PK = ProteinKinasesActivated.Dequeue();
                    IonChannel IC = IonChannelDetached.Dequeue();

                    //激活的蛋白酶与离子通道结合
                    IC.Combine(PK);

                    //离子通道激活
                    IonChannelCombined.Enqueue(IC);
                }

                //离子通道进出离子
                foreach (IonChannel IC in IonChannelCombined)
                {
                    IC.Operate(GetVoltage());
                }

                
                foreach (ProteinPhosphatase PP in ProteinPhosphatases)
                {
                    if (IonChannelCombined.Count == 0) break;

                    IonChannel IC = IonChannelCombined.Dequeue();

                    //蛋白磷酸酶使蛋白激酶与离子通道分离
                    IC.Detach(ProteinKinasesInactivated);

                    //从而离子通道失活
                    IonChannelDetached.Enqueue(IC);
                }

                Thread.Sleep(new TimeSpan(10000000));
            }
        }

        public void EffectorOperator()
        {
            while (true)
            {

                Thread.Sleep(new TimeSpan(10000000));
            }
        }

        public int GetVoltage()
        {
            //电位差
            int vol = 0;

            //电量和
            int q = 0;

            foreach (Ion ion in this.Ions.Values)
            {
                q += ion.Count * Ion.Valency[(int)ion.IonType];
            }

            //计算电位差
            //U = Q * C
            vol = (int)(q * Capacitance);

            return vol;
        }

    }

    /// <summary>
    /// 第一信使
    /// </summary>
    public class FirstMessenger
    {

        public FirstMessenger()
        {
        }
    }

    /// <summary>
    /// 受体
    /// </summary>
    public class Receptor
    {
        FirstMessenger firstMessenger = null;

        int ActivateCount = 10;

        public Receptor()
        {

        }

        //激活一定数量的G蛋白
        public void Activate(Queue<GProtein> gProteinsActivated, Queue<GProtein> gProteinsInactivated)
        {
            for (int i = 0; i < ActivateCount; i++)
            {
                if (gProteinsInactivated.Count == 0) break;

                gProteinsActivated.Enqueue(gProteinsInactivated.Dequeue());
            }
        }

        //结合第一信使
        public void Combine(FirstMessenger firstMessenger)
        {
            this.firstMessenger = firstMessenger;
        }

        //分离第一信使
        public void Detach(Queue<FirstMessenger> FirstMessengersDetached)
        {
            FirstMessengersDetached.Enqueue(this.firstMessenger);

            this.firstMessenger = null;
        }
    }

    public class GProtein
    {
        public bool IsActivated = false;

        public GProtein()
        {

        }

    }

    //第二信使酶
    public class SecondMessengerEnzyme
    {
        public GProtein GProtein = null;

        public SecondMessengerEnzyme() { }

        //结合G蛋白
        public void Combine(GProtein gProtein)
        {
            this.GProtein = gProtein;
        }

        //分离G蛋白
        public void Detach(Queue<GProtein> gProteinsInactivated)
        {
            gProteinsInactivated.Enqueue(this.GProtein);

            this.GProtein = null;
        }

        public void Operate(Queue<SecondMessenger> secondMessengerActivated, Queue<SecondMessenger> secondMessengerInactivated)
        {
            //激活
            if (secondMessengerInactivated.Count > 0)
                secondMessengerActivated.Enqueue(secondMessengerInactivated.Dequeue());

            ////抑制
            //if (secondMessengerActivated.Count > 0)
            //    secondMessengerInactivated.Enqueue(secondMessengerActivated.Dequeue());

        }
    }

    //第二信使
    public class SecondMessenger
    {
        public int Count = 0;

        public SecondMessenger(int count)
        {
            this.Count = count;
        }

        public void Activate(Queue<ProteinKinase> proteinKinasesActivated, Queue<ProteinKinase> proteinKinasesInactivated)
        {
            for (int i = 0; i < this.Count; i++)
            {
                if (proteinKinasesInactivated.Count == 0) break;

                //激活蛋白激酶
                proteinKinasesActivated.Enqueue(proteinKinasesInactivated.Dequeue());
            }
        }
    }

    //蛋白激酶
    public class ProteinKinase
    {
        public ProteinKinase() { }
    }

    //磷酸蛋白酶
    public class ProteinPhosphatase
    {
        public ProteinPhosphatase() { }
    }

    //离子类型
    public enum IonType
    {
        K = 0,
        Na = 1,
        Ca = 2,
        Cl = 3,
        Other = 4,
    }

    //离子
    public class Ion
    {
        //离子平衡电位
        public static int[] Potential = new int[] { -80, 62, 123, -65, 0 };

        //离子价
        public static int[] Valency = new int[] { 1, 1, 2, -1, 0 };

        public IonType IonType = IonType.Other;

        public int Count = 0;

        public Ion(IonType ionType, int count)
        {
            this.IonType = ionType;
        }

    }

    //离子通道
    public class IonChannel
    {
        //离子
        public Ion Ion = null;

        //电导
        public int Conductance = 0;

        public ProteinKinase ProteinKinase = null;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="ion">离子</param>
        /// <param name="conductance">电导</param>
        /// <param name="isActivated">是否激活</param>
        public IonChannel(Ion ion, int conductance)
        {
            this.Ion = ion;

            this.Conductance = conductance;
        }

        public void Combine(ProteinKinase proteinKinase)
        {
            this.ProteinKinase = proteinKinase;
        }

        public void Detach(Queue<ProteinKinase> ProteinKinasesDetached)
        {
            ProteinKinasesDetached.Enqueue(this.ProteinKinase);

            this.ProteinKinase = null;
        }

        /// <summary>
        /// 操作
        /// </summary>
        /// <param name="voltage">电压</param>
        public void Operate(int voltage)
        {
            this.Ion.Count -= (voltage - Ion.Potential[(int)IonType.K]) * this.Conductance;
        }
    }

    //离子泵
    public class IonPump
    {
        public Ion Ion = null;

        public int Count;

        /// <summary>
        /// 离子泵
        /// </summary>
        /// <param name="ion">离子</param>
        /// <param name="count">泵入的离子数:正的为泵入,负的为泵出</param>
        public IonPump(Ion ion, int count)
        {
            this.Ion = ion;

            this.Count = count;
        }

        public void Operate()
        {
            if (this.Count > 0 && this.Ion.Count < -1000)
            {
                this.Ion.Count += this.Count;
            }
            else if (this.Count < 0 && this.Ion.Count > 1000)
            {
                this.Ion.Count += this.Count;
            }
        }
    }
}
